package com.baidu.disconf.client.common.model;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.baidu.disconf.client.common.constants.SupportFileTypeEnum;
import com.baidu.disconf.client.config.DisClientConfig;
import com.baidu.disconf.client.support.utils.ClassUtils;
import com.baidu.disconf.core.common.utils.ClassLoaderUtil;
import com.baidu.disconf.core.common.utils.OsUtil;
import com.gitee.hermer.boot.jee.commons.collection.StringCache;
import com.gitee.hermer.boot.jee.commons.utils.StringUtils;
import com.gitee.hermer.engine.jars.app.sdk.EngineAppClassLoader;



/**
 * 閰嶇疆鏂囦欢琛ㄧず
 *
 * @author liaoqiqi
 * @version 2014-5-20
 */
public class DisconfCenterFile extends DisconfCenterBaseModel {

	protected static final Logger LOGGER = LoggerFactory.getLogger(DisconfCenterFile.class);

	// -----key: 閰嶇疆鏂囦欢涓殑椤瑰悕
	// -----value: 榛樿鍊�
	private Map<String, FileItemValue> keyMaps = new HashMap<String, FileItemValue>();

	// 棰濆鐨勯厤缃暟鎹紝闈炴敞瑙ｅ紡浣跨敤瀹冩潵瀛樺偍
	private Map<String, Object> additionalKeyMaps = new HashMap<String, Object>();

	// 鏄惁鏄潪娉ㄨВ娉ㄥ叆鏂瑰紡
	private boolean isTaggedWithNonAnnotationFile = false;

	// 閰嶇疆鏂囦欢绫�
	private Class<?> cls;

	// 鏂囦欢鍚�
	private String fileName;

	// 閰嶇疆鏂囦欢 鎸囧畾璺緞涓�
	private String targetDirPath;

	// 鏂囦欢绫诲瀷
	private SupportFileTypeEnum supportFileTypeEnum = SupportFileTypeEnum.ANY;

	public Class<?> getCls() {
		return cls;
	}

	public void setCls(Class<?> cls) {
		this.cls = cls;
	}

	public String getFileName() {
		return fileName;
	}

	public void setFileName(String fileName) {
		this.fileName = fileName;
	}

	public Map<String, FileItemValue> getKeyMaps() {
		return keyMaps;
	}

	public void setKeyMaps(Map<String, FileItemValue> keyMaps) {
		this.keyMaps = keyMaps;
	}

	public Map<String, Object> getAdditionalKeyMaps() {
		return additionalKeyMaps;
	}

	public void setAdditionalKeyMaps(Map<String, Object> additionalKeyMaps) {
		this.additionalKeyMaps = additionalKeyMaps;
	}

	public SupportFileTypeEnum getSupportFileTypeEnum() {
		return supportFileTypeEnum;
	}

	public void setSupportFileTypeEnum(SupportFileTypeEnum supportFileTypeEnum) {
		this.supportFileTypeEnum = supportFileTypeEnum;
	}

	public boolean isTaggedWithNonAnnotationFile() {
		return isTaggedWithNonAnnotationFile;
	}

	public void setIsTaggedWithNonAnnotationFile(boolean isTaggedWithNonAnnotationFile) {
		this.isTaggedWithNonAnnotationFile = isTaggedWithNonAnnotationFile;
	}

	public String getTargetDirPath() {
		return targetDirPath;
	}

	public void setTargetDirPath(String targetDirPath) {
		this.targetDirPath = targetDirPath;
	}

	@Override
	public String toString() {
		return "\n\tDisconfCenterFile [\n\tkeyMaps=" + keyMaps + "\n\tcls=" + cls + "\n\tfileName=" + fileName
				+ "\n\ttargetDirPath=" + targetDirPath +
				super.toString() + "]";
	}

	@Override
	public String infoString() {
		return "\n\tDisconfCenterFile [\n\tkeyMaps=" + keyMaps + "\n" +
				"\tadditionalKeyMaps=" + additionalKeyMaps + "\n\tcls=" + cls + super.infoString() + "]";
	}

	/**
	 * 鑾峰彇鍙互琛ㄧず鐨凨eyMap瀵�
	 */
	public Map<String, Object> getKV() {

		// 闈炴敞瑙ｅ紡鐨�
		if (keyMaps.size() == 0) {
			return additionalKeyMaps;
		}

		//
		// 娉ㄨВ寮忕殑
		//
		Map<String, Object> map = new HashMap<String, Object>();
		for (String key : keyMaps.keySet()) {
			map.put(key, keyMaps.get(key).getValue());
		}

		return map;
	}

	/**
	 * 閰嶇疆鏂囦欢鐨勮矾寰�
	 */
	public String getFilePath() {

		// 涓嶆斁鍒癱lasspath, 鍒欐枃浠惰矾寰勬牴鎹� userDefineDownloadDir 鏉ヨ缃�
		if (!DisClientConfig.getInstance().enableLocalDownloadDirInClassPath) {
			return OsUtil.pathJoin(DisClientConfig.getInstance().userDefineDownloadDir, fileName);
		}
		ClassLoader loader = Thread.currentThread().getContextClassLoader();
		if(loader instanceof EngineAppClassLoader){
			try{
				StringCache resourcePath = ((EngineAppClassLoader)loader).getAppExternalConfsPath();
				if (StringUtils.isNotBlank(targetDirPath)) {
					return OsUtil.pathJoin(resourcePath.toString(), targetDirPath,fileName);
				}
				return OsUtil.pathJoin(resourcePath.toString(),fileName);
			}catch (Exception e) {
				LOGGER.error(e.getMessage(),e);
				return null;
			}
		}else{
			if (targetDirPath != null) {

				if (targetDirPath.startsWith("/")) {
					return OsUtil.pathJoin(targetDirPath, fileName);
				}

				return OsUtil.pathJoin(ClassLoaderUtil.getClassPath(), targetDirPath, fileName);
			}

			return OsUtil.pathJoin(ClassLoaderUtil.getClassPath(), fileName);
		}
	}

	/**
	 * 閰嶇疆鏂囦欢鐨勮矾寰�
	 */
	public String getFileDir() {
		ClassLoader loader = Thread.currentThread().getContextClassLoader();
		if(loader instanceof EngineAppClassLoader){
			try{
				StringCache resourcePath = ((EngineAppClassLoader)loader).getAppExternalConfsPath();
				if (StringUtils.isNotBlank(targetDirPath)) {
					return OsUtil.pathJoin(resourcePath.toString(), targetDirPath);
				}
				return resourcePath.toString();
			}catch (Exception e) {
				LOGGER.error(e.getMessage(),e);
				return null;
			}
		}else{
			// 鑾峰彇鐩稿浜巆lasspath鐨勮矾寰�
			if (targetDirPath != null) {

				if (targetDirPath.startsWith("/")) {
					return OsUtil.pathJoin(targetDirPath);
				}

				return OsUtil.pathJoin(ClassLoaderUtil.getClassPath(), targetDirPath);
			}

			return ClassLoaderUtil.getClassPath();
		}
	}

	/**
	 * 閰嶇疆鏂囦欢Item椤硅〃绀猴紝鍖呮嫭浜嗗�硷紝杩樻湁鍏剁被鍨�
	 *
	 * @author liaoqiqi
	 * @version 2014-6-16
	 */
	public static class FileItemValue {

		private Object value;
		private Field field;
		private Method setMethod;

		public Object getValue() {
			return value;
		}

		public void setValue(Object value) {
			this.value = value;
		}

		public void setField(Field field) {
			this.field = field;
		}

		/**
		 * 鏄惁鏄潤鎬佸煙
		 *
		 * @return
		 */
		public boolean isStatic() {
			return Modifier.isStatic(field.getModifiers());
		}

		/**
		 * 璁剧疆value, 浼樺厛浣跨敤 setter method, 鐒跺悗鍏舵鏄弽灏�
		 *
		 * @param value
		 */
		public Object setValue4StaticFileItem(Object value) throws Exception {

			try {
				if (setMethod != null) {
					setMethod.invoke(null, value);
				} else {
					field.set(null, value);
				}

			} catch (Exception e) {
				LOGGER.warn(e.toString());
			}

			return value;
		}

		public Object setValue4FileItem(Object object, Object value) throws Exception {

			try {
				if (setMethod != null) {
					setMethod.invoke(object, value);
				} else {
					field.set(object, value);
				}
			} catch (Exception e) {
				LOGGER.warn(e.toString());
			}

			return value;
		}

		/**
		 * 杩斿洖鍊�
		 *
		 * @param fieldValue
		 *
		 * @return
		 *
		 * @throws Exception
		 */
		public Object getFieldValueByType(Object fieldValue) throws Exception {
			return ClassUtils.getValeByType(field.getType(), fieldValue);
		}

		public Object getFieldDefaultValue(Object object) throws Exception {
			return field.get(object);
		}

		@Override
		public String toString() {
			return "FileItemValue{" +
					"value=" + value +
					", field=" + field +
					", setMethod=" + setMethod +
					'}';
		}

		public FileItemValue(Object value, Field field) {
			super();
			this.value = value;
			this.field = field;
		}

		public FileItemValue(Object value, Field field, Method setMethod) {
			super();
			this.value = value;
			this.field = field;
			this.setMethod = setMethod;
		}
	}
}
